package com.ruoyi.orders.controller;

import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.Data;

import cn.hutool.json.JSONUtil;
import com.ruoyi.outuser.domain.OutUser;
import com.ruoyi.outuser.mapper.OutUserMapper;
import com.ruoyi.outuser.service.IOutUserService;
import com.ruoyi.trip.domain.Trip;
import com.ruoyi.trip.service.ITripService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.orders.domain.Orders;
import com.ruoyi.orders.service.IOrdersService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

import static com.ruoyi.utils.HttpClientHelper.sendGet;

/**
 * 预约订单Controller
 * 
 * @author shz
 * @date 2024-07-17
 */
@RestController
@RequestMapping("/orders/orders")
public class OrdersController extends BaseController
{
    @Autowired
    private IOrdersService ordersService;

    /**
     * 查询预约订单列表
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:list')")
    @GetMapping("/list")
    public TableDataInfo list(Orders orders)
    {
        startPage();
        List<Orders> list = ordersService.selectOrdersList(orders);
        return getDataTable(list);
    }

    /**
     * 导出预约订单列表
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:export')")
    @Log(title = "预约订单", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, Orders orders)
    {
        List<Orders> list = ordersService.selectOrdersList(orders);
        ExcelUtil<Orders> util = new ExcelUtil<Orders>(Orders.class);
        util.exportExcel(response, list, "预约订单数据");
    }

    /**
     * 获取预约订单详细信息
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(ordersService.selectOrdersById(id));
    }

    /**
     * 新增预约订单
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:add')")
    @Log(title = "预约订单", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody Orders orders)
    {
        return toAjax(ordersService.insertOrders(orders));
    }

    /**
     * 修改预约订单
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:edit')")
    @Log(title = "预约订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Orders orders)
    {
        return toAjax(ordersService.updateOrders(orders));
    }

    /**
     * 删除预约订单
     */
    @PreAuthorize("@ss.hasPermi('orders:orders:remove')")
    @Log(title = "预约订单", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(ordersService.deleteOrdersByIds(ids));
    }




    /**
     * 预约订单添加学分
     */
    @Resource
    OutUserMapper outUserMapper;
    @Resource
    ITripService tripService;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @PreAuthorize("@ss.hasPermi('orders:orders:addCourseScore')")
    @Log(title = "预约订单添加学分", businessType = BusinessType.INSERT)
    @PostMapping("{baseName}/{ids}/{studyCourses}")
    public AjaxResult addCourseScore(@PathVariable("baseName") String baseName,@PathVariable("ids") Long[] ids, @PathVariable("studyCourses") Integer[] studyCourses) {

        String lockKey = "orders:addCourseScoreLock:";
        String lockValue = UUID.randomUUID().toString(); // 使用随机UUID作为锁的值，便于解锁时验证
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        try {
            // 尝试获取锁，设置锁的超时时间为30秒
            Boolean lockAcquired = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, Duration.ofSeconds(1));
            if (Boolean.FALSE.equals(lockAcquired)) {
                // 如果锁没有被获取，返回错误信息
                return toAjaxByAddStudyScore(0 );
            }
            if(stringRedisTemplate.hasKey("orders:addCourseScoreIds:"+baseName+":"+formattedDate)){
                return toAjaxByAddStudyScore(0 );
            }
            // 锁获取成功，执行临界区代码
            int row = 0;
            for (int i = 0; i < ids.length; i++) {

                row += outUserMapper.updateCourseScore(ids[i], studyCourses[i]);
                stringRedisTemplate.opsForList().leftPush("orders:addCourseScoreIds:"+baseName+":"+formattedDate, String.valueOf(ids[i]));
                stringRedisTemplate.opsForList().leftPush("orders:addCourseScore:"+baseName+":"+formattedDate , String.valueOf(studyCourses[i]));
            }

            return toAjaxByAddStudyScore(1);
        } finally {
            // 释放锁，这里需要先验证锁的持有者
            String currentValue = stringRedisTemplate.opsForValue().get(lockKey);
            if (lockValue.equals(currentValue)) {
                stringRedisTemplate.delete(lockKey);
            }
        }
    }



    @PreAuthorize("@ss.hasPermi('orders:orders:revert')")
    @Log(title = "撤回添加学分", businessType = BusinessType.DELETE)
    @DeleteMapping("/revert/{baseName}")
    public AjaxResult revertCourseScore(@PathVariable String baseName) {
        String lockKey = "orders:deleteCourseScoreLock:";
        String lockValue = UUID.randomUUID().toString(); // 使用随机UUID作为锁的值，便于解锁时验证
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        try {
            // 尝试获取锁，设置锁的超时时间为30秒
            Boolean lockAcquired = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, Duration.ofSeconds(30));
            if (Boolean.FALSE.equals(lockAcquired)) {
                // 如果锁没有被获取，返回错误信息
                return toAjaxByAddStudyScore(0 );
            }
            if(!stringRedisTemplate.hasKey("orders:addCourseScoreIds:"+baseName+":"+formattedDate)){
                return toAjaxByAddStudyScore(0 );
            }

            List<String> range = stringRedisTemplate.opsForList().range("orders:addCourseScoreIds:" + baseName+":"+formattedDate, 0, -1);
            List<String> range2 = stringRedisTemplate.opsForList().range("orders:addCourseScore:" +baseName+":"+ formattedDate, 0, -1);
            List<Long> idsList=new ArrayList<>();
            for (String s : range) {
                idsList.add(Long.valueOf(s));
            }
            List<Integer> courseList=new ArrayList<>();
            for (String s : range2) {
                courseList.add(Integer.valueOf(s));
            }
            // 锁获取成功，执行临界区代码
            int row = 0;
            for (int i = 0; i < idsList.size(); i++) {
                row += outUserMapper.updateCourseScore(idsList.get(i), -courseList.get(i));
            }
            stringRedisTemplate.delete("orders:addCourseScoreIds:"+baseName+":"+formattedDate);
            stringRedisTemplate.delete("orders:addCourseScore:"+baseName+":"+formattedDate);


            return toAjaxByAddStudyScore(1);
        } finally {
            // 释放锁，这里需要先验证锁的持有者
            String currentValue = stringRedisTemplate.opsForValue().get(lockKey);
            if (lockValue.equals(currentValue)) {
                stringRedisTemplate.delete(lockKey);
            }
        }
    }

    @PreAuthorize("@ss.hasPermi('orders:orders:isShow')")
    @GetMapping("/isShow/{baseName}")
    public Boolean isShow(@PathVariable String baseName){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        return stringRedisTemplate.hasKey("orders:addCourseScoreIds:"+baseName+":"+formattedDate);
    }
    @GetMapping("/showSign/{baseName}")
    public Boolean showSign(@PathVariable String baseName){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        return stringRedisTemplate.hasKey("orders:sign:"+baseName+":"+formattedDate);
    }

    @GetMapping("/sendSign/{baseName}")
    public Boolean sendSign(@PathVariable String baseName){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        stringRedisTemplate.opsForValue().set("orders:sign:"+baseName+":"+formattedDate,"1");
        return true;
    }



    @GetMapping("/closeSign/{baseName}")
    public Boolean closeSign(@PathVariable String baseName){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化日期
        String formattedDate = currentDate.format(formatter);
        return stringRedisTemplate.delete("orders:sign:"+baseName+":"+formattedDate);

    }

}
